﻿using System;
using System.Collections.Generic;
using MySql.Simple.Mapper.Finders;
using MySql.Simple.Mapper.Readers;

namespace MySql.Simple.Mapper.Structures
{
    public class Table
    {
        private readonly Connection connection;
        private readonly string tableName;
        private readonly Type type;

        /// <summary>
        /// Initializes a new instance of the <see cref="Table{T}"/> class.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="connection">The connection.</param>
        public Table(Type type, Connection connection)
        {
            this.connection = connection;
            this.type = type;

            tableName = TableNameFinder.Find(type);
        }

        /// <summary>
        /// Creates the columns for the <see cref="Table"/> in the underlying database.
        /// </summary>
        public void CreateColumns()
        {
            var columns = ColumnFinder.Find(type);

            foreach (var column in columns)
            {
                if (!ColumnNames.Contains(column.Name))
                {
                    Commands.Columns.AddCommand.Execute(column, tableName, connection);
                }
            }
        }

        /// <summary>
        /// Creates the keys for the <see cref="Table"/> in the underlying database.
        /// </summary>
        public void CreateForeignKeys()
        {
            var foreignKeys = ForeignKeyFinder.Find(type);

            foreach (var foreignKey in foreignKeys)
            {
                Commands.ForeignKeys.AddCommand.Execute(foreignKey, connection);
            }
        }

        public void CreateIndicies()
        {
            var indices = IndexFinder.Find(type);

            foreach (var index in indices)
            {
                Commands.Indicies.AddCommand.Execute(index, connection);
                Commands.Indicies.AddCommand.Execute(index, connection);
            }
        }


        /// <summary>
        /// Gets a list of all the columns in the underlying SQL table
        /// </summary>
        /// <returns></returns>
        public IList<string> ColumnNames
        {
            get
            {
                return StringReader.Read(string.Format("SHOW COLUMNS FROM `{0}`;", tableName), connection);
            }
        }

        /// <summary>
        /// Returns a boolean value indicating whether this table exists.
        /// </summary>
        /// <returns></returns>
        public bool Exists()
        {
            return Commands.Tables.ExistsCommand.Execute(tableName, connection);
        }

        /// <summary>
        /// Creates this instance.
        /// </summary>
        public void Create()
        {
            Commands.Tables.CreateCommand.Execute(type, connection);
        }

        /// <summary>
        /// Empties this instance.
        /// </summary>
        public void Empty()
        {
            Commands.Tables.EmptyCommand.Execute(type, connection);            
        }

        public ColumnCollection GetColumns()
        {
            return ColumnFinder.Find(type);
        }
    }

    /// <summary>
    /// Represents a table in a <see cref="Database"/>.
    /// </summary>
    public class Table <T> : Table where T : new()
    {
        public Table(Connection connection) : base(typeof(T), connection)
        {
        }
    }
}